/* modules/console.c 
 * 
 * This file is part of xnix. 
 * 
 * XNIX is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * XNIX is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with XNIX. If not, see <https://www.gnu.org/licenses/>
 */ 




#include <sys/types.h>

#include <kernel/init.h>
#include <kernel/module.h>

#include <modules/console.h>

#include <arch/io.h>


__uint16_t pos = 0;
__uint16_t x = 0, y = 0;

#define POS2XY(pos) x = pos % 80; y = pos / 80;

static __uint16_t read_cursor(void);
static void update_cursor(void);

void raw_putc(__uint16_t, __uint8_t, char);
void cano_putc(char);


int __init init_console(void) {
	pos = read_cursor();

	POS2XY(pos);

	cano_putc('\n');

	return 0;
}


static __uint16_t read_cursor(void) {
	__uint16_t rv = 0;

	outb(CMD_POS_LO, VGA_INDEX);
	rv |= (__uint16_t) inb(VGA_DATA);

	outb(CMD_POS_HI, VGA_INDEX);
	rv |= ((__uint16_t) inb(VGA_DATA)) << 8;

	return rv;
}


void cano_putc(char c) {
	if (c == '\n') {
		y++;
		x = 0;

		goto out;
	}

	if (c == '\r') {
		x = 0;

		goto out;
	}

	if (c == '\t') {
		__uint32_t t = (x + TABSIZE - 1) & ~(TABSIZE - 1);

		if (t == x) 
			x += TABSIZE;

		else 
			x = t;

		if (x == COLMS) {
			y++;
			x = TABSIZE;
		}

		goto out;
	}

	raw_putc(pos++, 7, c);

	x++;

	if (x == COLMS) {
		y++;
		x = 0;
	}

out:
	update_cursor();

	return;
}


void raw_putc(__uint16_t pos, __uint8_t color, char c) {
	__uint16_t *fb = FB_ADDR + pos;

	*fb = (color << 8) + c;

	return;
}


void update_cursor(void) {
	pos = y * COLMS + x;

	outb(CMD_POS_LO, VGA_INDEX);
	outb(pos & 0xff, VGA_DATA);

	outb(CMD_POS_HI, VGA_INDEX);
	outb((pos >> 8) & 0xff, VGA_DATA);

	return;
}


module_init(init_console);


